package com.meida.module.bus.provider.api.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.StaticLog;
import com.alibaba.fastjson.util.TypeUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.meida.common.utils.RedisUtils;
import com.meida.module.admin.client.entity.BaseUser;
import com.meida.module.admin.provider.service.BaseUserService;
import com.meida.module.bus.client.entity.*;
import com.meida.module.bus.client.entity.srmapi.oa.*;
import com.meida.module.bus.provider.api.service.SyncSrmService;
import com.meida.module.bus.provider.mapper.BusReceiptDeliveryReqMapper;
import com.meida.module.bus.provider.service.*;
import com.meida.module.system.client.entity.SysDict;
import com.meida.module.system.client.entity.SysDictData;
import com.meida.module.system.provider.service.SysDictDataService;
import com.meida.module.system.provider.service.SysDictService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class PmsOaUtil {
    @Autowired
    private BusVersionService busVersionService;
    @Autowired
    private BusMaterialPlan100Service plan100Service;
    @Autowired
    private BusMaterialPlan200Service plan200Service;
    @Autowired
    private BusMaterialPackage100Service package100Service;
    @Autowired
    private BusMaterialPackage200Service package200Service;
    @Autowired
    private BusMaterialService busMaterialService;
    @Autowired
    private BusOaApprovalService busOaApprovalService;
    @Autowired
    private PmsApiUtil pmsApiUtil;
    @Autowired
    private SyncSrmService syncSrmService;
    @Autowired
    private BaseUserService userService;
    @Autowired
    private SysDictDataService dictDataService;
    @Autowired
    private SysDictService dictService;
    @Autowired
    private BusProjectService projectService;
    @Autowired
    private BusOaApprovalSyncService oaApprovalSyncService;
    @Resource
    private BusReceiptDeliveryReqMapper busReceiptDeliveryReqMapper;
    @Autowired
    private RedisUtils redisUtils;

    /**
     * PMS->OA审批流程保存
     */
    public void saveOrUpdateBusOaApproval(BusOaApproval busOaApproval) {
        busOaApprovalService.saveOrUpdate(busOaApproval);
    }

    /**
     * PMS->OA获取审批记录
     */
    public BusOaApproval getSingleBusOaApproval(Long pmsMainKey, String pmsFlow) {
        Map<String, Object> searchMap = Maps.newHashMap();
        searchMap.put("pmsMainKey", pmsMainKey);
        searchMap.put("pmsFlow", pmsFlow);
        Collection<BusOaApproval> busOaApprovals = busOaApprovalService.listByMap(searchMap);
        if (0 < busOaApprovals.size()) {
            return busOaApprovals.stream().findFirst().get();
        }

        return null;
    }

    /**
     * 分包/材料-修正变更/追加变更的内容更新到母表
     * 0 材料 1：分包
     *
     * @return false 合并失败 true 合并成功
     */
    @ApiOperation("材料-修正变更/追加变更的内容更新到母表")
    public Boolean updateMaterialBase(Long projectId, Integer ver, Integer kind) {
        StaticLog.info("-----updateMaterialBase-------start");
        Map<String, Object> searchMap = Maps.newHashMap();
        searchMap.put(ApiConstants.MAP_PROJECTID, projectId);
        searchMap.put(ApiConstants.MAP_VERSIONSTATUS, ApiConstants.INT_ZERO);
        searchMap.put(ApiConstants.MAP_APPLAYSTATUS, 2);
        Map<Long, List<Object>> beMap = Maps.newHashMap();

//        if (ApiConstants.INT_ZERO == kind) {
        // 材料
        if (ApiConstants.VER_100 == ver) {
            StaticLog.debug("-----updateMaterialBase------mergeDataMap-100材料-start");
            plan100Service.listByMap(searchMap).stream().forEach(plan100 -> {
                mergeDataMap(beMap, plan100);
            });
            StaticLog.debug("-----updateMaterialBase------mergeDataMap-100材料-end");
        } else {
            StaticLog.debug("-----updateMaterialBase------mergeDataMap-200材料-start");
            plan200Service.listByMap(searchMap).stream().forEach(plan200 -> {
                mergeDataMap(beMap, plan200);
            });
            StaticLog.debug("-----updateMaterialBase------mergeDataMap-200材料-end");
        }
//        } else {
//            // 分包
//            if (ApiConstants.VER_100 == ver) {
//                StaticLog.debug("-----updateMaterialBase------mergeDataMap-100分包-start");
//                package100Service.listByMap(searchMap).stream().forEach(package100 -> {
//                    mergeDataMap(beMap, package100);
//                });
//                StaticLog.debug("-----updateMaterialBase------mergeDataMap-100分包-end");
//            } else {
//                StaticLog.debug("-----updateMaterialBase------mergeDataMap-200分包-start");
//                package200Service.listByMap(searchMap).stream().forEach(package200 -> {
//                    mergeDataMap(beMap, package200);
//                });
//                StaticLog.debug("-----updateMaterialBase------mergeDataMap-200分包-end");
//            }
//        }

        StaticLog.debug("-----updateMaterialBase------合并父子节点并更新--start");
        // 合并父子节点并更新
        mergePlanData(beMap, ver, kind);
        StaticLog.debug("-----updateMaterialBase------合并父子节点并更新--end");

        StaticLog.debug("-----updateMaterialBase------更新临时为正式--start");
        // 更新临时为正式
        updPlanData(beMap, ver, kind);
        StaticLog.debug("-----updateMaterialBase------更新临时为正式--end");

        Boolean rs = Boolean.TRUE;
        StaticLog.debug("-----updateMaterialBase-------start");

        return rs;
    }

    /**
     * 分包/材料-修正变更/追加变更的内容更新到母表
     * 0 材料 1：分包
     *
     * @return false 合并失败 true 合并成功
     */
    @ApiOperation("分包-修正变更/追加变更的内容更新到母表")
    public Boolean updateMaterialBaseForPackage(Long projectId, String majorCode, String packageNo, Integer ver, String userName) throws Exception {
        StaticLog.info("-----updateMaterialBaseForPackage-------start");
        Map<String, Object> searchMap = Maps.newHashMap();
        searchMap.put(ApiConstants.MAP_PROJECTID, projectId);
        searchMap.put(ApiConstants.MAP_VERSIONSTATUS, ApiConstants.INT_ZERO);
        Map<Long, List<Object>> beMap = Maps.newHashMap();
        int kind = 1;
        // 分包
        if (ApiConstants.VER_100 == ver) {
            StaticLog.debug("-----updateMaterialBaseForPackage------mergeDataMap-100分包-start");
            package100Service.listByMap(searchMap).stream().forEach(package100 -> {
                mergeDataMap(beMap, package100);
            });
            StaticLog.debug("-----updateMaterialBaseForPackage------mergeDataMap-100分包-end");
        } else {
            StaticLog.debug("-----updateMaterialBaseForPackage------mergeDataMap-200分包-start");
            package200Service.listByMap(searchMap).stream().forEach(package200 -> {
                mergeDataMap(beMap, package200);
            });
            StaticLog.debug("-----updateMaterialBaseForPackage------mergeDataMap-200分包-end");
        }

        StaticLog.debug("-----updateMaterialBaseForPackage------合并父子节点并更新--start");
        // 合并父子节点并更新
        mergePlanData(beMap, ver, kind);
        StaticLog.debug("-----updateMaterialBaseForPackage------合并父子节点并更新--end");

        StaticLog.debug("-----updateMaterialBaseForPackage------更新临时为正式--start");
        // 更新临时为正式
        updPlanData(beMap, ver, kind);
        StaticLog.debug("-----updateMaterialBaseForPackage------更新临时为正式--end");

        StaticLog.debug("-----getBusMaterialPackage------节点数据合并完成，判断是否需要发送合同变更接口。");
        StaticLog.debug("-----getBusMaterialPackage------SRM接口发送--start");
        StaticLog.debug("-----projectId：" + projectId);
        StaticLog.debug("-----majorCode:" + majorCode);
        StaticLog.debug("-----packageNo:" + packageNo);
        StaticLog.debug("-----ver:" + ver);
        StaticLog.debug("-----getBusMaterialPackage------SRM接口发送--start");
        syncSrmService.planChange(projectId, majorCode, packageNo, ver, userName);
        StaticLog.debug("-----getBusMaterialPackage------SRM接口发送--end");

        Boolean rs = Boolean.TRUE;
        StaticLog.debug("-----updateMaterialBaseForPackage-------start");

        return rs;
    }

    /**
     * 分包/材料-修正变更/追加变更的内容更新到母表
     * 0 材料 1：分包
     *
     * @return false 合并失败 true 合并成功
     */
    @ApiOperation("分包-修正变更/追加变更的内容更新到母表----无同步，只合并")
    public Boolean updateMaterialBaseForPackageSingleNoSync(Long projectId, String majorCode, String packageNo, Integer ver, String userName) throws Exception {
        StaticLog.info("-----updateMaterialBaseForPackageSingleNoSync-------start");
        Map<String, Object> searchMap = Maps.newHashMap();
        searchMap.put(ApiConstants.MAP_PROJECTID, projectId);
        searchMap.put(ApiConstants.MAP_VERSIONSTATUS, ApiConstants.INT_ZERO);
        Map<Long, List<Object>> beMap = Maps.newHashMap();
        int kind = 1;
        // 分包
        if (ApiConstants.VER_100 == ver) {
            StaticLog.debug("-----updateMaterialBaseForPackage------mergeDataMap-100分包-start");
            package100Service.listByMap(searchMap).stream().forEach(package100 -> {
                mergeDataMap(beMap, package100);
            });
            StaticLog.debug("-----updateMaterialBaseForPackage------mergeDataMap-100分包-end");
        } else {
            StaticLog.debug("-----updateMaterialBaseForPackage------mergeDataMap-200分包-start");
            package200Service.listByMap(searchMap).stream().forEach(package200 -> {
                mergeDataMap(beMap, package200);
            });
            StaticLog.debug("-----updateMaterialBaseForPackage------mergeDataMap-200分包-end");
        }

        StaticLog.debug("-----updateMaterialBaseForPackage------合并父子节点并更新--start");
        // 合并父子节点并更新
        mergePlanData(beMap, ver, kind);
        StaticLog.debug("-----updateMaterialBaseForPackage------合并父子节点并更新--end");

        StaticLog.debug("-----updateMaterialBaseForPackage------更新临时为正式--start");
        // 更新临时为正式
        updPlanData(beMap, ver, kind);
        StaticLog.debug("-----updateMaterialBaseForPackage------更新临时为正式--end");

        StaticLog.info("-----updateMaterialBaseForPackageSingleNoSync-------end");
        return true;
    }

    private void updPlanData(Map<Long, List<Object>> beMap, Integer ver, Integer kind) {
        List<Object> subUpds = Lists.newArrayList();
        for (Long parentId : beMap.keySet()) {
            subUpds.addAll(beMap.get(parentId));
        }

        if (0 < subUpds.size()) {
            if (ApiConstants.INT_ZERO == kind) {
                // 材料
                if (ApiConstants.VER_100 == ver) {
                    List<BusMaterialPlan100> upd100 = Lists.newArrayList();
                    subUpds.stream().forEach(subObj -> {
                        BusMaterialPlan100 updObj = (BusMaterialPlan100) subObj;
                        updObj.setVersionStatus(ApiConstants.INT_ONE);
                        upd100.add(updObj);
                    });
                    if (0 < upd100.size()) {
                        plan100Service.updateBatchById(upd100);
                    }

                } else {
                    List<BusMaterialPlan200> upd200 = Lists.newArrayList();
                    subUpds.stream().forEach(subObj -> {
                        BusMaterialPlan200 updObj = (BusMaterialPlan200) subObj;
                        updObj.setVersionStatus(ApiConstants.INT_ONE);
                        upd200.add(updObj);
                    });
                    if (0 < upd200.size()) {
                        plan200Service.updateBatchById(upd200);
                    }
                }

            } else {
                if (ApiConstants.VER_100 == ver) {
                    List<BusMaterialPackage100> upd100 = Lists.newArrayList();
                    subUpds.stream().forEach(subObj -> {
                        BusMaterialPackage100 updObj = (BusMaterialPackage100) subObj;
                        updObj.setVersionStatus(ApiConstants.INT_ONE);
                        upd100.add(updObj);
                    });
                    if (0 < upd100.size()) {
                        package100Service.updateBatchById(upd100);
                    }
                } else {
                    List<BusMaterialPackage200> upd200 = Lists.newArrayList();
                    subUpds.stream().forEach(subObj -> {
                        BusMaterialPackage200 updObj = (BusMaterialPackage200) subObj;
                        updObj.setVersionStatus(ApiConstants.INT_ONE);
                        upd200.add(updObj);
                    });
                    if (0 < upd200.size()) {
                        package200Service.updateBatchById(upd200);
                    }
                }
            }
        }
    }

    /**
     * 合并父子节点并更新计划数据
     *
     * @param beMap
     * @param ver
     * @param kind
     */
    private void mergePlanData(Map<Long, List<Object>> beMap, Integer ver, Integer kind) {
        List<BusMaterial> mainUpds = Lists.newArrayList();
        List<Object> subUpds = Lists.newArrayList();
        for (Long parentId : beMap.keySet()) {
            // 获取计划子表父级节点Obj
            Object planOrPackObjectForUpd = getPlanOrPackageObj(ver, kind, parentId);

            if (ApiConstants.INT_ZERO == kind) {
                // 100预算成本工程量/200预算成本工程量/采购计划量/剩余采购量/在途采购量/到货量 更新到父级节点Obj
                getUpdValForParentForPlan(beMap.get(parentId), planOrPackObjectForUpd);
            } else {
                // 100预算成本工程量/200预算成本工程量/合同到货量1~10 更新到父级节点Obj
                getUpdValForParentForPackage(beMap.get(parentId), planOrPackObjectForUpd);
            }

            // 计划数据更新对象收集
            subUpds.add(planOrPackObjectForUpd);

            // 获取母表更新对象
            Long meterialId = PmsToolUtil.getLongValue(planOrPackObjectForUpd, ApiConstants.INVOKE_GET_MATERIALID);
            BusMaterial busMaterialParent = busMaterialService.getById(meterialId);
            // 100/200预算成本工程量
            BigDecimal costQuantity = ApiConstants.VER_100 == ver ? PmsToolUtil.getBigDecimalValue(planOrPackObjectForUpd, ApiConstants.INVOKE_GET_COSTQUANTITY100) : PmsToolUtil.getBigDecimalValue(planOrPackObjectForUpd, ApiConstants.INVOKE_GET_COSTQUANTITY200);
            // 更新母表对象中的预算成本相关数据
            PmsApiUtil.updateBudget(busMaterialParent, costQuantity);
            // 母表主数据更新对象收集
            mainUpds.add(busMaterialParent);
        }
        if (0 < subUpds.size()
            && 0 < mainUpds.size()) {
            // 更新计划表
            pmsApiUtil.updatePlanPackageData(subUpds, kind, ver);
            // 更新母表
            busMaterialService.updateBatchById(mainUpds);
        }
    }

    /**
     * 100预算成本工程量/200预算成本工程量/采购计划量/剩余采购量/在途采购量/到货量 更新到父级节点Obj
     *
     * @param ppObjects              计算用的map
     * @param planOrPackObjectForUpd 父级节点Obj
     * @return
     */
    private void getUpdValForParentForPlan(List<Object> ppObjects, Object planOrPackObjectForUpd) {
        Map<String, BigDecimal> rs = Maps.newHashMap();
        // 100预算成本工程量
        BigDecimal costQuantity100 = new BigDecimal(String.valueOf(getValForBigDecimal(planOrPackObjectForUpd, ApiConstants.INVOKE_GET_COSTQUANTITY100)));
        // 200预算成本工程量
        BigDecimal costQuantity200 = new BigDecimal(String.valueOf(getValForBigDecimal(planOrPackObjectForUpd, ApiConstants.INVOKE_GET_COSTQUANTITY200)));
        // 采购计划量
        BigDecimal planPurchaseCount = new BigDecimal(String.valueOf(getValForBigDecimal(planOrPackObjectForUpd, ApiConstants.INVOKE_GET_PLANPURCHASECOUNT)));
        // 剩余采购量
        BigDecimal endPurchaseCount = new BigDecimal(String.valueOf(getValForBigDecimal(planOrPackObjectForUpd, ApiConstants.INVOKE_GET_ENDPURCHASECOUNT)));
        // 在途采购量
        BigDecimal ztPurchaseCount = new BigDecimal(String.valueOf(getValForBigDecimal(planOrPackObjectForUpd, ApiConstants.INVOKE_GET_ZTPURCHASECOUNT)));
        // 到货量
        BigDecimal dhPurchaseCount = new BigDecimal(String.valueOf(getValForBigDecimal(planOrPackObjectForUpd, ApiConstants.INVOKE_GET_DHPURCHASECOUNT)));

        for (Object obj : ppObjects) {
            // 100预算成本工程量
            costQuantity100 = NumberUtil.add(costQuantity100, new BigDecimal(String.valueOf(getValForBigDecimal(obj, ApiConstants.INVOKE_GET_COSTQUANTITY100))));
            // 200预算成本工程量
            costQuantity200 = NumberUtil.add(costQuantity200, new BigDecimal(String.valueOf(getValForBigDecimal(obj, ApiConstants.INVOKE_GET_COSTQUANTITY200))));
            // 采购计划量
            planPurchaseCount = NumberUtil.add(planPurchaseCount, new BigDecimal(String.valueOf(getValForBigDecimal(obj, ApiConstants.INVOKE_GET_PLANPURCHASECOUNT))));
            // 剩余采购量
            endPurchaseCount = NumberUtil.add(endPurchaseCount, new BigDecimal(String.valueOf(getValForBigDecimal(obj, ApiConstants.INVOKE_GET_ENDPURCHASECOUNT))));
            // 在途采购量
            ztPurchaseCount = NumberUtil.add(ztPurchaseCount, new BigDecimal(String.valueOf(getValForBigDecimal(obj, ApiConstants.INVOKE_GET_ZTPURCHASECOUNT))));
            // 到货量
            dhPurchaseCount = NumberUtil.add(dhPurchaseCount, new BigDecimal(String.valueOf(getValForBigDecimal(obj, ApiConstants.INVOKE_GET_DHPURCHASECOUNT))));

        }

        // 100预算成本工程量 更新
        setValue(planOrPackObjectForUpd, ApiConstants.INVOKE_SET_CostQuantity100, costQuantity100);
        // 200预算成本工程量 更新
        setValue(planOrPackObjectForUpd, ApiConstants.INVOKE_SET_CostQuantity200, costQuantity200);
        // 采购计划量
        setValue(planOrPackObjectForUpd, ApiConstants.INVOKE_SET_PLANPURCHASECOUNT, planPurchaseCount);
        // 剩余采购量
        setValue(planOrPackObjectForUpd, ApiConstants.INVOKE_SET_ENDPURCHASECOUNT, endPurchaseCount);
        // 在途采购量
        setValue(planOrPackObjectForUpd, ApiConstants.INVOKE_SET_ZTPURCHASECOUNT, ztPurchaseCount);
        // 到货量
        setValue(planOrPackObjectForUpd, ApiConstants.INVOKE_SET_DHPURCHASECOUNT, dhPurchaseCount);

    }

    /**
     * 100预算成本工程量/200预算成本工程量/合同到货量1~10 更新到父级节点Obj
     *
     * @param ppObjects              计算用的map
     * @param planOrPackObjectForUpd 父级节点Obj
     * @return
     */
    private void getUpdValForParentForPackage(List<Object> ppObjects, Object planOrPackObjectForUpd) {
        Map<String, BigDecimal> rs = Maps.newHashMap();
        // 100预算成本工程量
        BigDecimal costQuantity100 = new BigDecimal(String.valueOf(getValForBigDecimal(planOrPackObjectForUpd, ApiConstants.INVOKE_GET_COSTQUANTITY100)));
        // 200预算成本工程量
        BigDecimal costQuantity200 = new BigDecimal(String.valueOf(getValForBigDecimal(planOrPackObjectForUpd, ApiConstants.INVOKE_GET_COSTQUANTITY200)));

        Map<Integer, BigDecimal> dataMergeMap = Maps.newHashMap();
        // 设定父级节点的默认量
        for (int i = 1; i < ApiConstants.INT_ELEVEN; i++) {
            dataMergeMap.put(i, new BigDecimal(String.valueOf(getValForBigDecimal(planOrPackObjectForUpd, ApiConstants.INVOKE_GET_SUPPLIERNUM + i))));
        }

        for (Object obj : ppObjects) {
            // 100预算成本工程量
            costQuantity100 = NumberUtil.add(costQuantity100, new BigDecimal(String.valueOf(getValForBigDecimal(obj, ApiConstants.INVOKE_GET_COSTQUANTITY100))));
            // 200预算成本工程量
            costQuantity200 = NumberUtil.add(costQuantity200, new BigDecimal(String.valueOf(getValForBigDecimal(obj, ApiConstants.INVOKE_GET_COSTQUANTITY200))));

            for (int i = 1; i < ApiConstants.INT_ELEVEN; i++) {
                BigDecimal mergeData = dataMergeMap.get(i);
                dataMergeMap.put(i, NumberUtil.add(mergeData, new BigDecimal(String.valueOf(getValForBigDecimal(obj, ApiConstants.INVOKE_GET_SUPPLIERNUM + i)))));
            }
        }

        // 100预算成本工程量 更新
        setValue(planOrPackObjectForUpd, ApiConstants.INVOKE_SET_CostQuantity100, costQuantity100);
        // 200预算成本工程量 更新
        setValue(planOrPackObjectForUpd, ApiConstants.INVOKE_SET_CostQuantity200, costQuantity200);

        // 合同量1~10 更新
        for (int i = 1; i < ApiConstants.INT_ELEVEN; i++) {
            setValue(planOrPackObjectForUpd, ApiConstants.INVOKE_SET_SUPPLIERNUM + i, dataMergeMap.get(i));
        }

    }

    /**
     * 合并父子节点数据
     *
     * @param planBeforeMap 合并后的父子节点Map
     * @param planObj
     */
    private void mergeDataMap(Map<Long, List<Object>> planBeforeMap, Object planObj) {
        Long parentId = PmsToolUtil.getLongValue(planObj, ApiConstants.INVOKE_GET_PARENTID);
        if(0L == parentId) {
            return;
        }
        Long materialId = PmsToolUtil.getLongValue(planObj, ApiConstants.INVOKE_GET_MATERIALID);
        if (planBeforeMap.containsKey((parentId))) {
            planBeforeMap.get(parentId).add(planObj);
        } else {
            List<Object> planChild = Lists.newArrayList();
            planChild.add(planObj);
            planBeforeMap.put(parentId, planChild);
        }
    }

    /**
     * 获取需要更新的单条材料/分包-100/200Obj
     *
     * @param ver      版本
     * @param kind     0 材料 1 分包
     * @param parentId 父级节点
     * @return
     */
    private Object getPlanOrPackageObj(Integer ver, Integer kind, Long parentId) {
        Object rs = new Object();
        if (ApiConstants.INT_ZERO == kind) {
            rs = ApiConstants.VER_100 == ver ? plan100Service.getById(parentId) : plan200Service.getById(parentId);
        } else {
            rs = ApiConstants.VER_100 == ver ? package100Service.getById(parentId) : package200Service.getById(parentId);
        }
        return rs;
    }

//    private Object getVal(Object inObj, String method) {
//        Method resMethod = ReflectUtil.getMethod(inObj.getClass(), method);
//        try {
//            Object rs = resMethod.invoke(inObj);
//            if (null == rs) {
//                return new Object();
//            }
//            return resMethod.invoke(inObj);
//        } catch (IllegalAccessException e) {
//            e.printStackTrace();
//        } catch (InvocationTargetException e) {
//            e.printStackTrace();
//        }
//        return new Object();
//    }

    private Object getValForBigDecimal(Object inObj, String method) {
        Method resMethod = ReflectUtil.getMethod(inObj.getClass(), method);
        try {
            Object rs = resMethod.invoke(inObj);
            if (null == rs) {
                return "0";
            }
            return resMethod.invoke(inObj);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return new Object();
    }

    /**
     * 设定Val
     *
     * @param obj
     * @param method
     * @param val
     */
    public void setValue(Object obj, String method, Object val) {
        try {
            ReflectUtil.invoke(obj, method, val);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * getXmjlNm 查询项目经理UserName
     *
     * @param projectId 项目ID
     * @return 项目经理UserName
     */
    public String getXmjlNm(Long projectId) {
        BusProject busProject = projectService.getById(Long.valueOf(projectId));
        BaseUser busUser = getBaseUserByNickName(busProject.getProjectXm());
        return busUser.getUserName();
    }

    /**
     * nickName 查询用户信息
     *
     * @param nickName nickName
     * @return 用户信息
     */
    public BaseUser getBaseUserByNickName(String nickName) {
        Map<String, Object> searchMap = Maps.newHashMap();
        searchMap.put(ApiConstants.MAP_NICKNAME, nickName);
        Collection<BaseUser> baseUsers = userService.listByMap(searchMap);
        return baseUsers.stream().findFirst().get();
    }

    /**
     * 设定审批流item扩展字段
     *
     * @param bpmDo 扩展对象
     * @param calNm 扩展策略
     */
    public void setBpmDo(Object bpmDo, Object setObj, String calNm) {
        SysDict sysDict = dictService.findByType(calNm);
        if (null == sysDict) {
            return;
        }
        List<SysDictData> sysDictDatas = dictDataService.findByDictId(sysDict.getDictId());
        if (0 < sysDictDatas.size()) {
            sysDictDatas.stream().forEach(dicDetailObj -> {
                if (StrUtil.isNotEmpty(dicDetailObj.getDicDataValue())) {
                    PmsToolUtil.setValue(setObj,
                        ApiConstants.PARAM_SET + StrUtil.upperFirst(dicDetailObj.getDicDataTitle()),
                        PmsToolUtil.getStrValue(bpmDo, ApiConstants.PARAM_GET + StrUtil.upperFirst(dicDetailObj.getDicDataValue())));
                }
            });
        }
    }

    /**
     * 获取OA审批服务器URL
     *
     * @return
     */
    public String getOaBpmReqUrl() {
        // ApiConstants.OA_BPM_REQ_URL
        SysDict sysDict = dictService.findByType(ApiConstants.OA_INFO);
        List<SysDictData> sysDictDatas = dictDataService.findByDictId(sysDict.getDictId());
        String reqUrl = "";
        if (0 < sysDictDatas.size()) {
            SysDictData sysDictData = sysDictDatas.stream().filter(dickObj -> dickObj.getDicDataTitle().equals(ApiConstants.OA_BPM_REQ_URL)).findFirst().get();
            reqUrl = sysDictData.getDicDataValue();
        }
        return reqUrl;
    }

    /**
     * 获取OA审批预览URL
     *
     * @return
     */
    public String getApprovlUrlBase() {
        SysDict sysDict = dictService.findByType(ApiConstants.OA_INFO);
        List<SysDictData> sysDictDatas = dictDataService.findByDictId(sysDict.getDictId());
        String reqUrl = "";
        if (0 < sysDictDatas.size()) {
            SysDictData sysDictData = sysDictDatas.stream().filter(dickObj -> dickObj.getDicDataTitle().equals(ApiConstants.OA_APPROVL_URL_BASE)).findFirst().get();
            reqUrl = sysDictData.getDicDataValue();
        }
        return reqUrl;
    }

    public BusOaApprovalSync getBusOaApprovalSync(String appKind, Object... reqData) {
        // 工程量清单的100版本的审批
        if (ApiConstants.BUSINESS_APPROVAL_100.equals(appKind)) {
            Map<String, Object> searchMap = Maps.newHashMap();
            searchMap.put(ApiConstants.MAP_PROJECTID, reqData[0]);
            Collection<BusOaApprovalSync> busOaApprovalSyncs = oaApprovalSyncService.listByMap(searchMap);
            if (0 < busOaApprovalSyncs.size()) {
                return busOaApprovalSyncs.stream().findFirst().get();
            }
        } else if (ApiConstants.ENGINEER_APPROVAL_WZ_100_UPD.equals(appKind)) {
        } else if (ApiConstants.ENGINEER_APPROVAL_WZ_100_ADD.equals(appKind)) {
        } else if (ApiConstants.ENGINEER_APPROVAL_WZ_200_UPD.equals(appKind)) {
        } else if (ApiConstants.ENGINEER_APPROVAL_WZ_200_ADD.equals(appKind)) {
        } else if (ApiConstants.ENGINEER_APPROVAL_FB_100_UPD.equals(appKind)) {
        } else if (ApiConstants.ENGINEER_APPROVAL_FB_100_ADD.equals(appKind)) {
        } else if (ApiConstants.ENGINEER_APPROVAL_FB_200_UPD.equals(appKind)) {
        } else if (ApiConstants.ENGINEER_APPROVAL_FB_200_ADD.equals(appKind)) {
        }
        return null;
    }

    public void setBpmReqObj(BpmMainDo bpmMainDo, Object header, Collection<Object> details, String appKind) {
        if (null == header) {
            return;
        }
        // 设定扩展字段
        setBpmDo(header, bpmMainDo, appKind);
        bpmMainDo.setItem1(bpmMainDo.getUserNum());
        bpmMainDo.setItem2(DateUtil.today());
        bpmMainDo.setItem6(bpmMainDo.getUserNum());
        bpmMainDo.setItem8(bpmMainDo.getUserNum());
        List<BpmDetailDo> bpmDetailDoList = Lists.newArrayList();
        if (0 < details.size()) {
            details.stream().forEach(detailObj -> {
                BpmDetailDo bpmDetailDo = new BpmDetailDo();
                // 设定扩展字段
                setBpmDo(detailObj, bpmDetailDo, appKind + ApiConstants.BUSINESS_APPROVAL_DT);
                bpmDetailDoList.add(bpmDetailDo);
            });
        }
        if (0 < bpmDetailDoList.size()) {
            bpmMainDo.setBpmDetailDoList(bpmDetailDoList);
        }
    }

    /**
     * 获取临时版本数据
     *
     * @param appKind   种类
     * @param projectId 项目ID
     * @return 临时版本数据
     */
    public List<Object> getPlanPackData(String appKind, Long projectId) throws Exception {
        List<Object> rs = Lists.newArrayList();
//        Collection<Object> rs = Collections.EMPTY_LIST;
        Map<String, Object> searchMap = Maps.newHashMap();
        searchMap.put(ApiConstants.MAP_PROJECTID, projectId);
        // 0临时版本 1正式版本
        searchMap.put(ApiConstants.MAP_VERSIONSTATUS, 0);
        //设置查询物资数据审核状态为待审核
        if(ApiConstants.ENGINEER_APPROVAL_WZ_100_UPD.equals(appKind)
            || ApiConstants.ENGINEER_APPROVAL_WZ_100_ADD.equals(appKind)
            || ApiConstants.ENGINEER_APPROVAL_WZ_200_UPD.equals(appKind)
            || ApiConstants.ENGINEER_APPROVAL_WZ_200_ADD.equals(appKind)
        ) {
            searchMap.put(ApiConstants.MAP_APPLAYSTATUS, 4);
        } else {
            // 0未审核 1审批中 2审批完成
            searchMap.put(ApiConstants.MAP_APPLAYSTATUS, 1);
        }

        if (ApiConstants.ENGINEER_APPROVAL_WZ_100_UPD.equals(appKind)
            || ApiConstants.ENGINEER_APPROVAL_FB_100_UPD.equals(appKind)
            || ApiConstants.ENGINEER_APPROVAL_WZ_200_UPD.equals(appKind)
            || ApiConstants.ENGINEER_APPROVAL_FB_200_UPD.equals(appKind)
        ) {
            searchMap.put(ApiConstants.MAP_PLANTYPE, 1);
        } else if (
            ApiConstants.ENGINEER_APPROVAL_WZ_100_ADD.equals(appKind)
                || ApiConstants.ENGINEER_APPROVAL_FB_100_ADD.equals(appKind)
                || ApiConstants.ENGINEER_APPROVAL_WZ_200_ADD.equals(appKind)
                || ApiConstants.ENGINEER_APPROVAL_FB_200_ADD.equals(appKind)
        ) {
            searchMap.put(ApiConstants.MAP_PLANTYPE, 2);
        }

        if (ApiConstants.ENGINEER_APPROVAL_WZ_100_UPD.equals(appKind)
            || ApiConstants.ENGINEER_APPROVAL_WZ_100_ADD.equals(appKind)) {
            rs.addAll(plan100Service.listByMap(searchMap));
        } else if (ApiConstants.ENGINEER_APPROVAL_WZ_200_UPD.equals(appKind)
            || ApiConstants.ENGINEER_APPROVAL_WZ_200_ADD.equals(appKind)) {
            rs.addAll(plan200Service.listByMap(searchMap));

        } else if (ApiConstants.ENGINEER_APPROVAL_FB_100_UPD.equals(appKind)
            || ApiConstants.ENGINEER_APPROVAL_FB_100_ADD.equals(appKind)) {
            rs.addAll(package100Service.listByMap(searchMap));

        } else if (ApiConstants.ENGINEER_APPROVAL_FB_200_UPD.equals(appKind)
            || ApiConstants.ENGINEER_APPROVAL_FB_200_ADD.equals(appKind)) {
            rs.addAll(package200Service.listByMap(searchMap));
        }
        return rs;
    }


    /**
     * 获取审批流名称/ID
     *
     * @param appKind kind 0 审批流程名称， 审批流Num
     * @return
     */
    public String getWorkflowname(String appKind, Integer kind) {
        String bkStr = "";
        SysDict sysDict = dictService.findByType(ApiConstants.OA_OAROVAL);
        List<SysDictData> sysDictDatas = dictDataService.findByDictId(sysDict.getDictId());
        if (0 < sysDictDatas.size()) {
            if (sysDictDatas.stream().anyMatch(
                sysDataObj -> sysDataObj.getDicDataTitle().split(ApiConstants.LINE_HAIFENG)[0].equals(appKind)
            )) {
                SysDictData sysDictDataFilter = sysDictDatas.stream().filter(
                    sysDataObj -> sysDataObj.getDicDataTitle().split(ApiConstants.LINE_HAIFENG)[0].equals(appKind)).findFirst().get();
                if (0 == kind) {
                    bkStr = sysDictDataFilter.getDicDataTitle().split(ApiConstants.LINE_HAIFENG)[1];
                } else {
                    bkStr = sysDictDataFilter.getDicDataValue();
                }


            }
        }
        return bkStr;
    }

//    /**
//     * 获取审批流名称
//     *
//     * @param key key
//     * @return 名称
//     */
//    public String getBpmApprovalNm(String key) {
//        SysDict sysDict = dictService.findByType(ApiConstants.OA_OAROVAL);
//        List<SysDictData> sysDictDatas = dictDataService.findByDictId(sysDict.getDictId());
//        String bpmApprovalNm = "";
//        StaticLog.info("key:" + key);
//        if (0 < sysDictDatas.size()) {
//            sysDictDatas.stream().forEach(sysObj->{
//                StaticLog.info(sysObj.getDicDataTitle());
//                StaticLog.info(sysObj.getDicDataTitle().split(ApiConstants.LINE_HAIFENG)[0]);
//            });
//            if(sysDictDatas.stream().anyMatch(da -> da.getDicDataTitle().split(ApiConstants.LINE_HAIFENG)[0].equals(key))) {
//                SysDictData sysDictData = sysDictDatas.stream().filter(da -> da.getDicDataTitle().split(ApiConstants.LINE_HAIFENG)[0].equals(key)).findFirst().get();
//                bpmApprovalNm = sysDictData.getDicDataValue();
//            }
//        }
//        return bpmApprovalNm;
//    }

    public String getUserNameFromRedis(String requestId) {
        StaticLog.info("getUserNameFromRedis----start");
        Map map = redisUtils.getMap(requestId);
        if (null == map) {
            return "";
        }
        if (null == map.get(ApiConstants.REDIS_KEY_USERNAME)) {
            return "";
        }
        StaticLog.info("getUserNameFromRedis----end");
        return String.valueOf(map.get(ApiConstants.REDIS_KEY_USERNAME));
    }

    public Boolean updApplyStatus(Collection<Object> reqS, String flowNum, Integer approvalStatus) {
        if (ApiConstants.ENGINEER_APPROVAL_WZ_100_UPD.equals(flowNum)
            || ApiConstants.ENGINEER_APPROVAL_WZ_100_ADD.equals(flowNum)) {
            StaticLog.info("材料计划_100版本_修正变更/追加变更审批--updApplyStatus---start");
            List<BusMaterialPlan100> updList = Lists.newArrayList();
            reqS.stream().forEach(reqObj -> {
                BusMaterialPlan100 updObj = new BusMaterialPlan100();
                updObj.setMaterialPlanId(PmsToolUtil.getLongValue(reqObj, ApiConstants.INVOKE_GET_MATERIALPLANID));
                updObj.setApplayStatus(approvalStatus);
                updList.add(updObj);
            });
            if (0 < updList.size()) {
                plan100Service.updateBatchById(updList);
            }
            StaticLog.info("材料计划_100版本_修正变更/追加变更审批--updApplyStatus---end");
        } else if (ApiConstants.ENGINEER_APPROVAL_WZ_200_UPD.equals(flowNum)
            || ApiConstants.ENGINEER_APPROVAL_WZ_200_ADD.equals(flowNum)) {
            // 材料计划_200版本_修正变更审批
            StaticLog.info("材料计划_200版本_修正变更/追加变更审批--updApplyStatus---start");
            List<BusMaterialPlan200> updList = Lists.newArrayList();
            reqS.stream().forEach(reqObj -> {
                BusMaterialPlan200 updObj = new BusMaterialPlan200();
                updObj.setMaterialPlanId(PmsToolUtil.getLongValue(reqObj, ApiConstants.INVOKE_GET_MATERIALPLANID));
                updObj.setApplayStatus(approvalStatus);
                updList.add(updObj);
            });
            if (0 < updList.size()) {
                plan200Service.updateBatchById(updList);
            }
            StaticLog.info("材料计划_200版本_修正变更/追加变更审批--updApplyStatus---end");

        } else if (ApiConstants.ENGINEER_APPROVAL_FB_100_UPD.equals(flowNum)
            || ApiConstants.ENGINEER_APPROVAL_FB_100_ADD.equals(flowNum)) {
            // 分包计划_100版本_修正变更审批
            StaticLog.info("分包计划_100版本_修正变更/追加变更审批--updApplyStatus---start");
            List<BusMaterialPackage100> updList = Lists.newArrayList();
            reqS.stream().forEach(reqObj -> {
                BusMaterialPackage100 updObj = new BusMaterialPackage100();
                updObj.setMaterialPackage100Id(PmsToolUtil.getLongValue(reqObj, ApiConstants.INVOKE_GET_MATERIALPACKAGE100ID));
                updObj.setApplayStatus(approvalStatus);
                updList.add(updObj);
            });
            if (0 < updList.size()) {
                package100Service.updateBatchById(updList);
            }
            StaticLog.info("分包计划_100版本_修正变更/追加变更审批--updApplyStatus---end");

        } else if (ApiConstants.ENGINEER_APPROVAL_FB_200_UPD.equals(flowNum)
            || ApiConstants.ENGINEER_APPROVAL_FB_200_ADD.equals(flowNum)) {
            // 分包计划_200版本_追加变更审批
            StaticLog.info("分包计划_200版本_追加变更/追加变更审批--updApplyStatus---start");
            List<BusMaterialPackage200> updList = Lists.newArrayList();
            reqS.stream().forEach(reqObj -> {
                BusMaterialPackage200 updObj = new BusMaterialPackage200();
                updObj.setMaterialPackage100Id(PmsToolUtil.getLongValue(reqObj, ApiConstants.INVOKE_GET_MATERIALPACKAGE100ID));
                updObj.setApplayStatus(approvalStatus);
                updList.add(updObj);
            });
            if (0 < updList.size()) {
                package200Service.updateBatchById(updList);
            }
            StaticLog.info("分包计划_200版本_追加变更/追加变更审批--updApplyStatus---end");

        }
        return Boolean.TRUE;
    }

    // 检查分包业务的专业代码，工程包代码
    public Boolean chkFbApprovalInfo(Object reqData, String approvalKind) {
        if (ApiConstants.ENGINEER_APPROVAL_FB_100_UPD.equals(approvalKind)
            || ApiConstants.ENGINEER_APPROVAL_FB_100_ADD.equals(approvalKind)
            || ApiConstants.ENGINEER_APPROVAL_FB_200_UPD.equals(approvalKind)
            || ApiConstants.ENGINEER_APPROVAL_FB_200_ADD.equals(approvalKind)) {
            Map map = (Map) reqData;
            String majorCode = TypeUtils.castToString(map.get("majorCode"));
            String packageNo = TypeUtils.castToString(map.get("packageNo"));
            if(StrUtil.isEmpty(majorCode) || StrUtil.isEmpty(packageNo)) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    // 面向计划数据-记录同步子项目
    public void setSyncOaDetailListForPlanData(Collection<Object> reqS, List<BusOaApprovalSyncDetail> syncOaDetailList, String appKind) {
        reqS.stream().forEach(resObj->{
            BusOaApprovalSyncDetail busOaApprovalSyncDetail = new BusOaApprovalSyncDetail();
            busOaApprovalSyncDetail.setAppKind(appKind);
            busOaApprovalSyncDetail.setMajorCode(PmsToolUtil.getStrValue(resObj, ApiConstants.INVOKE_GET_MAJORCODE));
            busOaApprovalSyncDetail.setPackageNo(PmsToolUtil.getStrValue(resObj, ApiConstants.INVOKE_GET_PACKAGENO));
            // 物资项目
            if(ApiConstants.ENGINEER_APPROVAL_WZ_100_UPD.equals(appKind)
                || ApiConstants.ENGINEER_APPROVAL_WZ_100_ADD.equals(appKind)
                || ApiConstants.ENGINEER_APPROVAL_WZ_200_UPD.equals(appKind)
                || ApiConstants.ENGINEER_APPROVAL_WZ_200_ADD.equals(appKind)) {
                busOaApprovalSyncDetail.setPlanId(PmsToolUtil.getLongValue(resObj, ApiConstants.INVOKE_GET_MATERIALPLANID));
            } else if(ApiConstants.ENGINEER_APPROVAL_FB_100_UPD.equals(appKind)
                || ApiConstants.ENGINEER_APPROVAL_FB_100_ADD.equals(appKind)
                || ApiConstants.ENGINEER_APPROVAL_FB_200_UPD.equals(appKind)
                || ApiConstants.ENGINEER_APPROVAL_FB_200_ADD.equals(appKind)) {
                busOaApprovalSyncDetail.setPackageId(PmsToolUtil.getLongValue(resObj, ApiConstants.INVOKE_GET_MATERIALPACKAGE100ID));
            }
            syncOaDetailList.add(busOaApprovalSyncDetail);
        });
    }

    // 面向材料申请数据-记录同步子项目
    public void setSyncOaDetailListForApplayData(List<BusPurchaseDetails> detailReqs, List<BusOaApprovalSyncDetail> syncOaDetailList, String appKind) {
        detailReqs.stream().forEach(detailObj->{
            BusOaApprovalSyncDetail busOaApprovalSyncDetail = new BusOaApprovalSyncDetail();
            busOaApprovalSyncDetail.setAppKind(appKind);
            busOaApprovalSyncDetail.setPlanId(detailObj.getMaterialId());
            syncOaDetailList.add(busOaApprovalSyncDetail);
        });
    }

    // 面向分包录入数据-记录同步子项目
    public void setSyncOaDetailListForPackageApplayData(List<BusReport> busReportList, List<BusOaApprovalSyncDetail> syncOaDetailList, String appKind) {
        busReportList.stream().forEach(reportObj->{
            BusOaApprovalSyncDetail busOaApprovalSyncDetail = new BusOaApprovalSyncDetail();
            busOaApprovalSyncDetail.setAppKind(appKind);
            busOaApprovalSyncDetail.setPackageId(reportObj.getMaterialId());
            syncOaDetailList.add(busOaApprovalSyncDetail);
        });
    }

}
